import paramiko
import json
import logging
from datetime import datetime
from django.utils import timezone
from .models import DockerServer
import asyncio
import subprocess
import re

logger = logging.getLogger(__name__)


class DockerSSHManager:
    """Docker SSH连接管理器"""

    def __init__(self, docker_server):
        self.docker_server = docker_server
        self.ssh_client = None

    def connect(self):
        """建立SSH连接"""
        try:
            self.ssh_client = paramiko.SSHClient()
            self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

            # 获取连接信息
            conn_info = self.docker_server.get_ssh_connection_info()

            # 连接SSH
            if conn_info['key_path']:
                # 使用SSH密钥连接
                self.ssh_client.connect(
                    hostname=conn_info['host'],
                    port=conn_info['port'],
                    username=conn_info['username'],
                    key_filename=conn_info['key_path'],
                    timeout=10
                )
            else:
                # 使用密码连接
                self.ssh_client.connect(
                    hostname=conn_info['host'],
                    port=conn_info['port'],
                    username=conn_info['username'],
                    password=conn_info['password'],
                    timeout=10
                )

            logger.info(f"SSH连接成功: {self.docker_server.name}")
            return True

        except Exception as e:
            logger.error(f"SSH连接失败 {self.docker_server.name}: {str(e)}")
            return False

    def disconnect(self):
        """断开SSH连接"""
        if self.ssh_client:
            self.ssh_client.close()
            self.ssh_client = None

    def execute_command(self, command, timeout=30):
        """执行SSH命令"""
        if not self.ssh_client:
            if not self.connect():
                raise Exception("SSH连接失败")

        try:
            stdin, stdout, stderr = self.ssh_client.exec_command(command, timeout=timeout)

            # 读取输出
            stdout_data = stdout.read().decode('utf-8')
            stderr_data = stderr.read().decode('utf-8')
            exit_code = stdout.channel.recv_exit_status()

            if exit_code != 0:
                raise Exception(f"命令执行失败: {stderr_data}")

            return stdout_data.strip()

        except Exception as e:
            logger.error(f"命令执行失败 {command}: {str(e)}")
            raise

    def __enter__(self):
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.disconnect()


class DockerService:
    """Docker服务管理类"""

    def __init__(self, docker_server):
        self.docker_server = docker_server
        self.ssh_manager = DockerSSHManager(docker_server)

    def test_connection(self):
        """测试Docker服务器连接"""
        try:
            with self.ssh_manager as ssh:
                # 测试SSH连接
                ssh_result = ssh.execute_command('echo "SSH连接成功"')

                # 测试Docker是否安装
                docker_version = ssh.execute_command('docker --version')

                # 测试Docker是否运行
                docker_info = ssh.execute_command('docker info --format "{{json .}}"')

                # 更新服务器状态
                self.docker_server.connection_status = 'connected'
                self.docker_server.docker_version = docker_version
                self.docker_server.last_check_time = timezone.now()

                # 解析Docker信息
                try:
                    info_data = json.loads(docker_info)
                    self.docker_server.system_info = info_data
                    self.docker_server.docker_api_version = info_data.get('APIVersion', '')
                except:
                    pass

                self.docker_server.save()

                return {
                    'success': True,
                    'message': 'Docker服务器连接成功',
                    'docker_version': docker_version,
                    'ssh_status': 'connected'
                }

        except Exception as e:
            # 更新失败状态
            self.docker_server.connection_status = 'error'
            self.docker_server.last_check_time = timezone.now()
            self.docker_server.save()

            return {
                'success': False,
                'message': f'连接失败: {str(e)}',
                'error': str(e)
            }

    def get_system_info(self):
        """获取Docker系统信息"""
        try:
            with self.ssh_manager as ssh:
                # 获取Docker系统信息
                docker_info = ssh.execute_command('docker system info --format "{{json .}}"')
                info_data = json.loads(docker_info)

                # 获取Docker版本信息
                docker_version = ssh.execute_command('docker version --format "{{json .}}"')
                version_data = json.loads(docker_version)

                return {
                    'success': True,
                    'system_info': info_data,
                    'version_info': version_data
                }

        except Exception as e:
            logger.error(f"获取Docker系统信息失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_containers(self, all_containers=True):
        """获取容器列表"""
        try:
            with self.ssh_manager as ssh:
                # 构建命令
                cmd = 'docker ps --format "{{json .}}"'
                if all_containers:
                    cmd = 'docker ps -a --format "{{json .}}"'

                # 执行命令
                output = ssh.execute_command(cmd)

                containers = []
                if output:
                    for line in output.split('\n'):
                        if line.strip():
                            try:
                                container_data = json.loads(line)
                                # 转换字段名以匹配前端期望
                                formatted_container = {
                                    'id': container_data.get('ID', ''),
                                    'name': container_data.get('Names', ''),
                                    'image': container_data.get('Image', ''),
                                    'status': container_data.get('State', ''),
                                    'ports': container_data.get('Ports', ''),
                                    'created': container_data.get('CreatedAt', ''),
                                    'command': container_data.get('Command', ''),
                                    'size': container_data.get('Size', ''),
                                    'networks': container_data.get('Networks', ''),
                                    'mounts': container_data.get('Mounts', ''),
                                    'labels': container_data.get('Labels', ''),
                                    'running_for': container_data.get('RunningFor', ''),
                                    'local_volumes': container_data.get('LocalVolumes', ''),
                                    'raw_status': container_data.get('Status', '')
                                }
                                containers.append(formatted_container)
                            except json.JSONDecodeError:
                                continue

                return {
                    'success': True,
                    'containers': containers
                }

        except Exception as e:
            logger.error(f"获取容器列表失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_images(self):
        """获取镜像列表"""
        try:
            with self.ssh_manager as ssh:
                # 获取镜像列表
                output = ssh.execute_command('docker images --format "{{json .}}"')

                images = []
                if output:
                    for line in output.split('\n'):
                        if line.strip():
                            try:
                                image_data = json.loads(line)
                                # 格式化镜像数据
                                formatted_image = {
                                    'id': image_data.get('ID', ''),
                                    'repository': image_data.get('Repository', ''),
                                    'tag': image_data.get('Tag', ''),
                                    'digest': image_data.get('Digest', ''),
                                    'created_at': image_data.get('CreatedAt', ''),
                                    'created_since': image_data.get('CreatedSince', ''),
                                    'size': image_data.get('Size', ''),
                                    'shared_size': image_data.get('SharedSize', ''),
                                    'unique_size': image_data.get('UniqueSize', ''),
                                    'containers': image_data.get('Containers', ''),
                                    'virtual_size': image_data.get('VirtualSize', ''),
                                }
                                images.append(formatted_image)
                            except json.JSONDecodeError:
                                continue

                return {
                    'success': True,
                    'images': images
                }

        except Exception as e:
            logger.error(f"获取镜像列表失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def remove_image(self, image_id, force=False):
        """删除镜像"""
        try:
            with self.ssh_manager as ssh:
                # 构建删除命令
                cmd = f'docker rmi {image_id}'
                if force:
                    cmd += ' --force'

                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'镜像 {image_id} 删除成功',
                    'output': output
                }

        except Exception as e:
            logger.error(f"删除镜像失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }



    def pull_image(self, image_name, registry_info=None):
        """拉取镜像"""
        try:
            with self.ssh_manager as ssh:
                # 如果是Harbor镜像且提供了认证信息，先登录
                if registry_info and '/' in image_name and not image_name.startswith('docker.io'):
                    # 提取registry URL
                    registry_url = image_name.split('/')[0]

                    # 执行docker login
                    login_cmd = f'echo "{registry_info["password"]}" | docker login {registry_url} -u {registry_info["username"]} --password-stdin'
                    try:
                        login_output = ssh.execute_command(login_cmd)
                        logger.info(f"Harbor登录成功: {registry_url}")
                    except Exception as login_error:
                        logger.warning(f"Harbor登录失败: {str(login_error)}")
                        # 继续尝试拉取，可能是公开镜像

                # 拉取镜像
                cmd = f'docker pull {image_name}'
                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'镜像 {image_name} 拉取成功',
                    'output': output
                }

        except Exception as e:
            logger.error(f"拉取镜像失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def tag_image(self, source_image, target_image):
        """为镜像添加标签"""
        try:
            with self.ssh_manager as ssh:
                # 添加标签
                cmd = f'docker tag {source_image} {target_image}'
                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'镜像标签添加成功: {source_image} -> {target_image}',
                    'output': output
                }

        except Exception as e:
            logger.error(f"添加镜像标签失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def export_image(self, image_id, output_file):
        """导出镜像"""
        try:
            with self.ssh_manager as ssh:
                # 导出镜像
                cmd = f'docker save -o {output_file} {image_id}'
                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'镜像 {image_id} 导出成功到 {output_file}',
                    'output': output
                }

        except Exception as e:
            logger.error(f"导出镜像失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def export_image_for_download(self, image_id, local_output_file):
        """导出镜像并下载到本地"""
        try:
            with self.ssh_manager as ssh:
                # 在远程服务器上导出镜像到临时文件
                remote_temp_file = f'/tmp/{image_id.replace(":", "_").replace("/", "_")}.tar'
                cmd = f'docker save -o {remote_temp_file} {image_id}'
                output = ssh.execute_command(cmd)

                # 使用SFTP下载文件到本地
                sftp = ssh.ssh_client.open_sftp()
                sftp.get(remote_temp_file, local_output_file)
                sftp.close()

                # 清理远程临时文件
                ssh.execute_command(f'rm -f {remote_temp_file}')

                return {
                    'success': True,
                    'message': f'镜像 {image_id} 导出并下载成功到 {local_output_file}',
                    'output': output
                }

        except Exception as e:
            logger.error(f"导出并下载镜像失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def build_image(self, dockerfile_path, image_name, build_args=None):
        """构建镜像"""
        try:
            with self.ssh_manager as ssh:
                # 构建镜像
                cmd = f'docker build -t {image_name} {dockerfile_path}'
                if build_args:
                    for key, value in build_args.items():
                        cmd += f' --build-arg {key}={value}'

                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'镜像 {image_name} 构建成功',
                    'output': output
                }

        except Exception as e:
            logger.error(f"构建镜像失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def build_image_from_content(self, dockerfile_content, image_name, uploaded_files=None):
        """从Dockerfile内容构建镜像"""
        import uuid
        import base64

        try:
            with self.ssh_manager as ssh:
                # 在远程服务器上创建临时目录
                temp_dir = f'/tmp/docker_build_{uuid.uuid4().hex[:8]}'

                # 创建临时目录
                try:
                    ssh.execute_command(f'mkdir -p {temp_dir}')
                except Exception as e:
                    return {
                        'success': False,
                        'error': f'创建临时目录失败: {str(e)}'
                    }

                try:
                    # 写入Dockerfile
                    dockerfile_path = f'{temp_dir}/Dockerfile'
                    # 使用echo命令写入Dockerfile内容，处理特殊字符
                    dockerfile_b64 = base64.b64encode(dockerfile_content.encode('utf-8')).decode('ascii')
                    try:
                        ssh.execute_command(f'echo "{dockerfile_b64}" | base64 -d > {dockerfile_path}')
                    except Exception as e:
                        return {
                            'success': False,
                            'error': f'写入Dockerfile失败: {str(e)}'
                        }

                    # 处理上传的文件
                    if uploaded_files:
                        for filename, file_content in uploaded_files.items():
                            file_path = f'{temp_dir}/{filename}'
                            # 确保目录存在
                            dir_path = '/'.join(file_path.split('/')[:-1])
                            ssh.execute_command(f'mkdir -p {dir_path}')

                            # 写入文件内容
                            # 前端已经将文件转换为Base64，直接使用
                            if isinstance(file_content, str):
                                file_b64 = file_content
                            else:
                                # 如果不是字符串，转换为Base64
                                file_b64 = base64.b64encode(file_content).decode('ascii')

                            try:
                                ssh.execute_command(f'echo "{file_b64}" | base64 -d > {file_path}')
                            except Exception as e:
                                logger.warning(f'写入文件 {filename} 失败: {str(e)}')

                    # 构建镜像
                    cmd = f'cd {temp_dir} && docker build -t {image_name} .'
                    logger.info(f"执行Docker构建命令: {cmd}")

                    try:
                        output = ssh.execute_command(cmd)
                        logger.info(f"镜像构建成功: {image_name}")
                        return {
                            'success': True,
                            'message': f'镜像 {image_name} 构建成功',
                            'output': output
                        }
                    except Exception as e:
                        logger.error(f"镜像构建失败: {str(e)}")
                        return {
                            'success': False,
                            'error': f'构建失败: {str(e)}'
                        }

                finally:
                    # 清理临时目录
                    try:
                        ssh.execute_command(f'rm -rf {temp_dir}')
                        logger.info(f"已清理远程临时目录: {temp_dir}")
                    except Exception as e:
                        logger.warning(f"清理远程临时目录失败: {e}")

        except Exception as e:
            logger.error(f"构建镜像异常: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def inspect_image(self, image_id):
        """获取镜像详细信息"""
        try:
            with self.ssh_manager as ssh:
                # 获取镜像详细信息
                output = ssh.execute_command(f'docker inspect {image_id}')

                try:
                    image_info = json.loads(output)
                    return {
                        'success': True,
                        'data': image_info[0] if image_info else {}
                    }
                except json.JSONDecodeError:
                    return {
                        'success': False,
                        'error': '解析镜像信息失败'
                    }

        except Exception as e:
            logger.error(f"获取镜像详细信息失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def prune_images(self, dangling_only=True):
        """清理镜像"""
        try:
            with self.ssh_manager as ssh:
                # 清理镜像
                if dangling_only:
                    cmd = 'docker image prune -f'
                else:
                    cmd = 'docker image prune -a -f'

                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': '镜像清理完成',
                    'output': output
                }

        except Exception as e:
            logger.error(f"清理镜像失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def run_container_from_image(self, image_name, container_name=None, ports=None, volumes=None,
                                env_vars=None, command=None, args=None, restart_policy='no',
                                auto_remove=False, privileged=False, user=None, working_dir=None,
                                hostname=None, network_mode='default', memory_limit=None, cpu_limit=None):
        """从镜像运行容器"""
        try:
            with self.ssh_manager as ssh:
                # 构建运行命令
                cmd = 'docker run -d'

                # 添加容器名称
                if container_name:
                    cmd += f' --name {container_name}'

                # 添加重启策略
                if restart_policy and restart_policy != 'no':
                    cmd += f' --restart {restart_policy}'

                # 添加自动删除选项
                if auto_remove:
                    cmd += ' --rm'
                    # 如果设置了自动删除，不能使用-d参数
                    cmd = cmd.replace(' -d', '')

                # 添加特权模式
                if privileged:
                    cmd += ' --privileged'

                # 添加运行用户
                if user:
                    cmd += f' --user {user}'

                # 添加工作目录
                if working_dir:
                    cmd += f' --workdir {working_dir}'

                # 添加主机名
                if hostname:
                    cmd += f' --hostname {hostname}'

                # 添加网络模式
                if network_mode and network_mode != 'default':
                    cmd += f' --network {network_mode}'

                # 添加内存限制
                if memory_limit:
                    cmd += f' --memory {memory_limit}'

                # 添加CPU限制
                if cpu_limit:
                    cmd += f' --cpus {cpu_limit}'

                # 添加端口映射
                if ports:
                    for port_mapping in ports:
                        cmd += f' -p {port_mapping}'

                # 添加数据卷挂载
                if volumes:
                    for volume_mapping in volumes:
                        cmd += f' -v {volume_mapping}'

                # 添加环境变量
                if env_vars:
                    for key, value in env_vars.items():
                        # 对包含空格或特殊字符的值进行引号包装
                        if ' ' in str(value) or '"' in str(value):
                            cmd += f' -e {key}="{value}"'
                        else:
                            cmd += f' -e {key}={value}'

                # 添加镜像名称
                cmd += f' {image_name}'

                # 添加命令
                if command:
                    cmd += f' {command}'

                # 添加参数
                if args:
                    cmd += f' {args}'

                logger.info(f"执行Docker运行命令: {cmd}")
                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'容器从镜像 {image_name} 创建并启动成功',
                    'container_id': output.strip(),
                    'output': output,
                    'command': cmd
                }

        except Exception as e:
            logger.error(f"从镜像运行容器失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_networks(self):
        """获取网络列表（包含详细信息）"""
        try:
            with self.ssh_manager as ssh:
                # 先获取网络ID列表
                output = ssh.execute_command('docker network ls -q')

                networks = []
                if output:
                    network_ids = [line.strip() for line in output.split('\n') if line.strip()]

                    # 对每个网络获取详细信息
                    for network_id in network_ids:
                        try:
                            inspect_output = ssh.execute_command(f'docker network inspect {network_id}')
                            network_data = json.loads(inspect_output)

                            # docker network inspect 返回的是数组，取第一个元素
                            if isinstance(network_data, list) and len(network_data) > 0:
                                networks.append(network_data[0])
                            elif isinstance(network_data, dict):
                                networks.append(network_data)

                        except (json.JSONDecodeError, Exception) as e:
                            logger.warning(f"获取网络 {network_id} 详情失败: {str(e)}")
                            continue

                return {
                    'success': True,
                    'networks': networks
                }

        except Exception as e:
            logger.error(f"获取网络列表失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def create_network(self, name, driver='bridge', subnet=None, gateway=None, ip_range=None, labels=None, options=None):
        """创建网络"""
        try:
            with self.ssh_manager as ssh:
                # 构建创建网络命令
                cmd = f'docker network create --driver {driver}'

                # 添加IPAM配置
                if subnet or gateway or ip_range:
                    ipam_config = []
                    if subnet:
                        ipam_config.append(f'subnet={subnet}')
                    if gateway:
                        ipam_config.append(f'gateway={gateway}')
                    if ip_range:
                        ipam_config.append(f'ip-range={ip_range}')

                    if ipam_config:
                        cmd += f' --subnet {subnet}'
                        if gateway:
                            cmd += f' --gateway {gateway}'
                        if ip_range:
                            cmd += f' --ip-range {ip_range}'

                # 添加标签
                if labels:
                    for key, value in labels.items():
                        cmd += f' --label {key}={value}'

                # 添加选项
                if options:
                    for key, value in options.items():
                        cmd += f' --opt {key}={value}'

                # 添加网络名称
                cmd += f' {name}'

                logger.info(f"创建网络命令: {cmd}")
                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'网络 {name} 创建成功',
                    'network_id': output.strip()
                }

        except Exception as e:
            logger.error(f"创建网络失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def remove_network(self, network_id):
        """删除网络"""
        try:
            with self.ssh_manager as ssh:
                cmd = f'docker network rm {network_id}'
                logger.info(f"删除网络命令: {cmd}")
                ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'网络 {network_id} 删除成功'
                }

        except Exception as e:
            logger.error(f"删除网络失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def inspect_network(self, network_id):
        """获取网络详情"""
        try:
            with self.ssh_manager as ssh:
                cmd = f'docker network inspect {network_id}'
                output = ssh.execute_command(cmd)

                # 解析JSON输出
                network_data = json.loads(output)
                if isinstance(network_data, list) and len(network_data) > 0:
                    network_data = network_data[0]

                return {
                    'success': True,
                    'network': network_data
                }

        except Exception as e:
            logger.error(f"获取网络详情失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_volumes(self):
        """获取数据卷列表"""
        try:
            with self.ssh_manager as ssh:
                # 获取数据卷名称列表
                output = ssh.execute_command('docker volume ls --format "{{.Name}}"')

                volumes = []
                if output:
                    volume_names = [name.strip() for name in output.split('\n') if name.strip()]

                    # 为每个数据卷获取详细信息
                    for volume_name in volume_names:
                        try:
                            # 使用docker volume inspect获取详细信息
                            inspect_output = ssh.execute_command(f'docker volume inspect {volume_name}')
                            volume_data = json.loads(inspect_output)

                            if isinstance(volume_data, list) and len(volume_data) > 0:
                                vol_info = volume_data[0]

                                # 获取使用该数据卷的容器
                                containers_output = ssh.execute_command(f'docker ps -a --filter volume={volume_name} --format "{{{{.Names}}}}"')
                                connected_containers = [name.strip() for name in containers_output.strip().split('\n') if name.strip()]

                                volume = {
                                    'Name': vol_info.get('Name', volume_name),
                                    'Driver': vol_info.get('Driver', 'local'),
                                    'Mountpoint': vol_info.get('Mountpoint', ''),
                                    'Scope': vol_info.get('Scope', 'local'),
                                    'CreatedAt': vol_info.get('CreatedAt', ''),
                                    'Labels': vol_info.get('Labels', {}),
                                    'Options': vol_info.get('Options', {}),
                                    'ConnectedContainers': connected_containers,
                                    'ContainerCount': len(connected_containers)
                                }
                                volumes.append(volume)
                        except Exception as e:
                            logger.warning(f"获取数据卷 {volume_name} 详细信息失败: {str(e)}")
                            # 如果获取详细信息失败，添加基本信息
                            volume = {
                                'Name': volume_name,
                                'Driver': 'local',
                                'Mountpoint': f'/var/lib/docker/volumes/{volume_name}/_data',
                                'Scope': 'local',
                                'CreatedAt': '',
                                'Labels': {},
                                'Options': {},
                                'ConnectedContainers': [],
                                'ContainerCount': 0
                            }
                            volumes.append(volume)

                return {
                    'success': True,
                    'volumes': volumes
                }

        except Exception as e:
            logger.error(f"获取数据卷列表失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def create_volume(self, volume_name, driver='local', labels=None, options=None):
        """创建数据卷"""
        try:
            with self.ssh_manager as ssh:
                # 构建创建命令
                cmd = f'docker volume create'

                # 添加驱动
                if driver and driver != 'local':
                    cmd += f' --driver {driver}'

                # 添加标签
                if labels:
                    for key, value in labels.items():
                        cmd += f' --label {key}={value}'

                # 添加选项
                if options:
                    for key, value in options.items():
                        cmd += f' --opt {key}={value}'

                # 添加数据卷名称
                cmd += f' {volume_name}'

                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'数据卷 {volume_name} 创建成功',
                    'output': output
                }

        except Exception as e:
            logger.error(f"创建数据卷失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def inspect_volume(self, volume_name):
        """获取数据卷详情"""
        try:
            with self.ssh_manager as ssh:
                cmd = f'docker volume inspect {volume_name}'
                logger.error(f"DEBUG: 执行数据卷详情命令: {cmd}")
                output = ssh.execute_command(cmd)
                logger.error(f"DEBUG: 命令输出: {output}")

                # 解析JSON输出
                volume_data = json.loads(output)
                if isinstance(volume_data, list) and len(volume_data) > 0:
                    volume_data = volume_data[0]

                return {
                    'success': True,
                    'data': volume_data
                }

        except Exception as e:
            logger.error(f"获取数据卷详情失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def remove_volume(self, volume_name, force=False):
        """删除数据卷"""
        try:
            with self.ssh_manager as ssh:
                # 构建删除命令
                cmd = f'docker volume rm'
                if force:
                    cmd += ' --force'
                cmd += f' {volume_name}'

                output = ssh.execute_command(cmd)

                return {
                    'success': True,
                    'message': f'数据卷 {volume_name} 删除成功',
                    'output': output
                }

        except Exception as e:
            logger.error(f"删除数据卷失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def prune_volumes(self):
        """清理未使用的数据卷"""
        try:
            with self.ssh_manager as ssh:
                # 先查看有哪些数据卷
                list_cmd = 'docker volume ls'
                before_output = ssh.execute_command(list_cmd)
                logger.info(f"清理前的数据卷列表: {before_output}")

                # 执行清理命令
                prune_cmd = 'docker volume prune --force'
                output = ssh.execute_command(prune_cmd)
                logger.info(f"数据卷清理命令输出: {output}")

                # 再次查看数据卷列表
                after_output = ssh.execute_command(list_cmd)
                logger.info(f"清理后的数据卷列表: {after_output}")

                # 解析输出获取清理信息
                deleted_volumes = []
                space_reclaimed = 0

                # 解析清理输出
                lines = output.split('\n')
                for line in lines:
                    if 'deleted' in line.lower() or 'removed' in line.lower():
                        # 提取删除的数据卷信息
                        pass

                # 构建更详细的消息
                message = f'数据卷清理完成。命令输出: {output.strip()}'

                return {
                    'success': True,
                    'message': message,
                    'output': output,
                    'deleted_volumes': deleted_volumes,
                    'space_reclaimed': space_reclaimed
                }

        except Exception as e:
            logger.error(f"清理数据卷失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def update_statistics(self):
        """更新服务器统计信息"""
        try:
            # 获取各种资源的数量
            containers_result = self.get_containers(all_containers=True)
            images_result = self.get_images()
            networks_result = self.get_networks()
            volumes_result = self.get_volumes()

            if containers_result['success']:
                containers = containers_result['containers']
                self.docker_server.total_containers = len(containers)
                self.docker_server.running_containers = len([c for c in containers if c.get('State') == 'running'])

            if images_result['success']:
                self.docker_server.total_images = len(images_result['images'])

            if networks_result['success']:
                self.docker_server.total_networks = len(networks_result['networks'])

            if volumes_result['success']:
                self.docker_server.total_volumes = len(volumes_result['volumes'])

            self.docker_server.last_sync_time = timezone.now()
            self.docker_server.save()

            return True

        except Exception as e:
            logger.error(f"更新统计信息失败: {str(e)}")
            return False

    def start_container(self, container_id):
        """启动容器"""
        try:
            with self.ssh_manager as ssh:
                output = ssh.execute_command(f'docker start {container_id}')
                return {
                    'success': True,
                    'message': f'容器 {container_id} 启动成功',
                    'output': output
                }
        except Exception as e:
            logger.error(f"启动容器失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def stop_container(self, container_id):
        """停止容器"""
        try:
            with self.ssh_manager as ssh:
                output = ssh.execute_command(f'docker stop {container_id}')
                return {
                    'success': True,
                    'message': f'容器 {container_id} 停止成功',
                    'output': output
                }
        except Exception as e:
            logger.error(f"停止容器失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def restart_container(self, container_id):
        """重启容器"""
        try:
            with self.ssh_manager as ssh:
                output = ssh.execute_command(f'docker restart {container_id}')
                return {
                    'success': True,
                    'message': f'容器 {container_id} 重启成功',
                    'output': output
                }
        except Exception as e:
            logger.error(f"重启容器失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def remove_container(self, container_id, force=False):
        """删除容器"""
        try:
            with self.ssh_manager as ssh:
                cmd = f'docker rm {container_id}'
                if force:
                    cmd = f'docker rm -f {container_id}'
                output = ssh.execute_command(cmd)
                return {
                    'success': True,
                    'message': f'容器 {container_id} 删除成功',
                    'output': output
                }
        except Exception as e:
            logger.error(f"删除容器失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def prune_containers(self):
        """清理停止的容器"""
        try:
            with self.ssh_manager as ssh:
                output = ssh.execute_command('docker container prune --force')

                # 解析输出获取清理信息
                deleted_containers = []
                space_reclaimed = 0

                # 简单解析输出
                lines = output.split('\n')
                for line in lines:
                    if 'deleted' in line.lower() or 'removed' in line.lower():
                        # 提取删除的容器信息
                        pass

                return {
                    'success': True,
                    'message': '停止的容器清理完成',
                    'output': output,
                    'deleted_containers': deleted_containers,
                    'space_reclaimed': space_reclaimed
                }

        except Exception as e:
            logger.error(f"清理容器失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def get_container_logs(self, container_id, lines=100):
        """获取容器日志"""
        try:
            with self.ssh_manager as ssh:
                output = ssh.execute_command(f'docker logs --tail {lines} {container_id}')
                return {
                    'success': True,
                    'logs': output
                }
        except Exception as e:
            logger.error(f"获取容器日志失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def inspect_container(self, container_id):
        """获取容器详细信息"""
        try:
            with self.ssh_manager as ssh:
                output = ssh.execute_command(f'docker inspect {container_id}')

                # 解析JSON输出
                import json
                try:
                    inspect_data = json.loads(output)
                    # docker inspect返回的是数组，取第一个元素
                    if isinstance(inspect_data, list) and len(inspect_data) > 0:
                        container_info = inspect_data[0]
                    else:
                        container_info = inspect_data

                    return {
                        'success': True,
                        'data': container_info
                    }
                except json.JSONDecodeError as e:
                    logger.error(f"解析容器详细信息JSON失败: {str(e)}")
                    return {
                        'success': False,
                        'error': f'解析容器详细信息失败: {str(e)}'
                    }

        except Exception as e:
            logger.error(f"获取容器详细信息失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }

    def push_image_to_harbor(self, source_image, target_image, harbor_url, username, password):
        """推送镜像到Harbor"""
        try:
            with self.ssh_manager as ssh_manager:
                # 清理Harbor URL
                clean_url = harbor_url.replace('https://', '').replace('http://', '')

                # 1. 先给镜像打标签
                tag_command = f'docker tag {source_image} {target_image}'
                stdin, stdout, stderr = ssh_manager.ssh_client.exec_command(tag_command)
                tag_error = stderr.read().decode('utf-8').strip()

                if tag_error and 'Error' in tag_error:
                    return {
                        'success': False,
                        'error': f'镜像标签失败: {tag_error}'
                    }

                # 2. 使用认证信息推送镜像
                push_command = f'echo "{password}" | docker login {clean_url} -u {username} --password-stdin && docker push {target_image}'
                stdin, stdout, stderr = ssh_manager.ssh_client.exec_command(push_command, timeout=300)  # 5分钟超时

                push_output = stdout.read().decode('utf-8').strip()
                push_error = stderr.read().decode('utf-8').strip()

                if push_error and ('Error' in push_error or 'denied' in push_error.lower()):
                    return {
                        'success': False,
                        'error': f'推送镜像失败: {push_error}'
                    }

                if 'Login Succeeded' in push_output or 'pushed' in push_output.lower():
                    return {
                        'success': True,
                        'message': '镜像推送成功',
                        'output': push_output
                    }
                else:
                    return {
                        'success': False,
                        'error': f'推送可能失败: {push_output}'
                    }

        except Exception as e:
            logger.error(f"推送镜像到Harbor失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }


def test_docker_connection(host, ssh_port, ssh_username, ssh_password, ssh_key_path=None):
    """测试Docker连接（静态方法）"""
    try:
        ssh_client = paramiko.SSHClient()
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # 连接SSH
        if ssh_key_path:
            ssh_client.connect(
                hostname=host,
                port=ssh_port,
                username=ssh_username,
                key_filename=ssh_key_path,
                timeout=10
            )
        else:
            ssh_client.connect(
                hostname=host,
                port=ssh_port,
                username=ssh_username,
                password=ssh_password,
                timeout=10
            )

        # 测试Docker
        stdin, stdout, stderr = ssh_client.exec_command('docker --version', timeout=10)
        docker_version = stdout.read().decode('utf-8').strip()
        exit_code = stdout.channel.recv_exit_status()

        if exit_code != 0:
            error_msg = stderr.read().decode('utf-8')
            raise Exception(f"Docker命令执行失败: {error_msg}")

        # 测试Docker服务状态
        stdin, stdout, stderr = ssh_client.exec_command('docker info', timeout=10)
        exit_code = stdout.channel.recv_exit_status()

        ssh_client.close()

        if exit_code != 0:
            return {
                'success': False,
                'message': 'Docker服务未运行或权限不足',
                'docker_version': docker_version
            }

        return {
            'success': True,
            'message': 'Docker连接测试成功',
            'docker_version': docker_version
        }

    except Exception as e:
        return {
            'success': False,
            'message': f'连接测试失败: {str(e)}',
            'error': str(e)
        }
